#include "app_buffer.h"
#include "stdlib.h"
#include "string.h"
#include "log/log.h"


//初始化生成小缓冲区 
static SubBuffer *init_sub_buffer(int size)
{
    SubBuffer *sub_buffer = (SubBuffer*)malloc(sizeof(SubBuffer));
    sub_buffer->ptr = (char*)malloc(size);
    sub_buffer->size = size;
    sub_buffer->len = 0;

    return sub_buffer;
}


//初始化 从外向内
Buffer* app_buffer_init(int size)
{
    //申请内存
    Buffer* buffer = (Buffer*)malloc(sizeof(Buffer));

    //初始化 内部属性
    buffer->sub_buffers[0] = init_sub_buffer(size);
    buffer->sub_buffers[1] = init_sub_buffer(size);
    buffer->read_index = 0;
    buffer->write_index = 1;

    //初始化创建读锁和写锁
    pthread_mutex_init(&buffer->read_lock, NULL);
    pthread_mutex_init(&buffer->write_lock, NULL);
    return buffer;
}

//释放 从内向外
void app_buffer_free(Buffer* buffer)
{
    free(buffer->sub_buffers[0]->ptr);
    free(buffer->sub_buffers[0]);
    free(buffer->sub_buffers[1]->ptr);
    free(buffer->sub_buffers[1]);
    free(buffer);
}

//写入数据
int app_buffer_write(Buffer* buffer, char* data, int len)
{
    //判断数据长度是否合法(不能超过255 -> 下面会用一个字节来存储len)
    if (len > 255)
    {
        log_error("data len is too long");
        return -1;
    }
    
    //加写锁
    log_debug("write lock");
    pthread_mutex_lock(&buffer->write_lock);
    
    //得到写的小buffer
    SubBuffer* w_buffer = buffer->sub_buffers[buffer->write_index];

    //判断小buffer是否写满
    if (w_buffer->size - w_buffer->len < len + 1)
    {
        log_error("buffer is full");
        //解写锁
        pthread_mutex_unlock(&buffer->write_lock);
        return -1;
    }
    

    //向小buffer中写入数据长度和数据
    w_buffer->ptr[w_buffer->len] = len;
    memcpy(w_buffer->ptr + w_buffer->len + 1, data, len);
    //更新小buffer中的len
    w_buffer->len += len + 1;
    //解写锁
    log_debug("write unlock");
    pthread_mutex_unlock(&buffer->write_lock);
    return 0;
}

void swap_sub_buffer(Buffer* buffer)//如果正在写,不能交换
{
    //加写锁
    log_debug("swap write lock");
    pthread_mutex_lock(&buffer->write_lock);
    int tmp = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = tmp;
    //解写锁
    log_debug("swap write unlock");
    pthread_mutex_unlock(&buffer->write_lock);
}

//读取数据
int app_buffer_read(Buffer* buffer, char* data_buf, int buf_size)
{
    //加读锁
    log_debug("read lock");
    pthread_mutex_lock(&buffer->read_lock);
    //得到读取的小buffer
    SubBuffer* r_buffer = buffer->sub_buffers[buffer->read_index];
    //如果当前读取的小buffer为空,则切换到另一个小buffer
    if (r_buffer->len == 0)
    {
        swap_sub_buffer(buffer);
        r_buffer = buffer->sub_buffers[buffer->read_index];
        //如果交换后还是空的,则说明没有数据,失败返回-1
        if (r_buffer->len == 0)
        {
            return -1;
        }
    }
    

    //读取数据长度
    int len = r_buffer->ptr[0];

    //判断容器大小是否足够
    if (len > buf_size)
    {
        log_error("buf_size is too small");
        return -1;
    }

    //读取对应的数据,保存到data_buf
    memcpy(data_buf, r_buffer->ptr + 1, len);
    //将后面未读取的数据全部移动到起始位置
    memmove(r_buffer->ptr, r_buffer->ptr + len + 1, r_buffer->size - len - 1);

    //更新小buffer中的len
    r_buffer->len -= len + 1;

    //解读锁
    log_debug("read unlock");
    pthread_mutex_unlock(&buffer->read_lock);
    return len;
}
